/**
 * 一个二维数组，#表示障碍物，点表示通路，S表示起点
 * 问是否存在从S开始且到S结束的简单路径，且长度大于等于4
 * 考虑到二维数组的图，如果S存在于一个点数不少于4的边双连通分量，则路径存在
 * 模板题
 */
#include <algorithm>
#include <bits/stdc++.h>
#include <numeric>
#include <bits/extc++.h>
using namespace std;

struct ECCTarjan{ // 边双连通分量

using weight_t = int;
using vi = vector<int>;

struct edge_t{
    int from;
    int to;
    weight_t w;
    edge_t(int a, int b, weight_t c):from(a),to(b),w(c){}
};

int N;
vector<edge_t> Edges;
vector<vi> G; // 编号从1开始

/// 点数和边数
void init(int n, int m){
    G.assign((N = n) + 1, {});
    Edges.clear();
    Edges.reserve(m + m); // 无向边
}

/// 双向边
void mkBiEdge(int a, int b, weight_t w=0){
    G[a].emplace_back(Edges.size());
    Edges.emplace_back(a, b, w);
    G[b].emplace_back(Edges.size());
    Edges.emplace_back(b, a, w);
}

/// 主函数
void Tarjan(){
    Dfn.assign(N + 1, 0);
    Low.assign(N + 1, 0);
    Stack.assign(N + 1, 0);
    Belong2ECC.assign(N + 1, 0);
    IsVisited.assign(Edges.size(), 0);
    Represent.assign(N + 1, 0);
    TimeStamp = ECCCnt = StackTop = 0;
    
    for(int i=1;i<=N;++i){
        if(0 == Dfn[i]){
            dfs(i, i);
        }
    }
    
    Represent.erase(Represent.begin() + ECCCnt, Represent.end());
    return;
}

void dfs(int u, int pre){
    Dfn[u] = Low[u] = ++TimeStamp;
    /// 入栈
    Stack[StackTop++] = u;
    
    int v, son = 0;
    for(auto i : G[u])if(not IsVisited[i]){
        IsVisited[i] = IsVisited[i ^ 1] = 1;
        const auto & e = Edges[i];
        
        
        if(0 == Dfn[v = e.to]){
            ++son;
            dfs(v, u);
            if(Low[v] < Low[u]) Low[u] = Low[v]; 
        }else if(Dfn[v] < Low[u]){
            Low[u] = Dfn[v];
        }
    }

    if(Low[u] == Dfn[u]){ // u和其上点在同一个边双中
        Represent[Belong2ECC[u] = ECCCnt] = u;
        do{
            Belong2ECC[v = Stack[--StackTop]] = ECCCnt;
            if(v < Represent[ECCCnt]) Represent[ECCCnt] = v;
        }while(v != u);
        ECCCnt += 1;
    }

    return;
}

vi Stack; // 辅助栈
int StackTop;
int TimeStamp;
vi Dfn, Low;

vi IsVisited;//边的标记数组，有重边时需用此数组进行判断
vi Belong2ECC;//点i属于第Bi个双连通分量，从0开始
vi Represent;//Ri表示第i个边双的代表，也就是编号最小的那个点
int ECCCnt;//双连通分量的数量


}T;

int H, W;
vector<string> Board;

int f(int r, int c){
    return r * W + c + 1;
}

bool proc(){
    int vn = H * W;
    T.init(vn, 2 * vn);

    int sidx = -1; // 起点的编号
    for(int i=0;i<H;++i)for(int j=0;j<W;++j){
        if('#' == Board[i][j]) continue;

        int u = f(i, j);  
        if('S' == Board[i][j]) sidx = u;
        
        if(i != H - 1 and '#' != Board[i + 1][j]){
            // if('S' == Board[i][j] or 'S' == Board[i + 1][j]) es.push_back(T.Edges.size());
            T.mkBiEdge(u, u + W);
        }
        if(j != W - 1 and '#' != Board[i][j + 1]){
            // if('S' == Board[i][j] or 'S' == Board[i][j + 1]) es.push_back(T.Edges.size());
            T.mkBiEdge(u, u + 1);
        }
    }

    T.Tarjan();

    int cnt = 0;
    for(int i=1;i<=vn;++i){
        if(T.Belong2ECC[i] == T.Belong2ECC[sidx]){
            if(++cnt >= 4) return true;
        }
    }
    return false;
}

void work(){
    cin >> H >> W;
    Board.assign(H, {});
    for(auto & s : Board) cin >> s;

    cout << (proc() ? "Yes\n" : "No\n");
    return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--) work();
    return 0;
}